#include "caiclient.h"

#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonValue>

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>

//#include "cryptopp/iterhash.h"
//#include "cryptopp/files.h"
//#include "cryptopp/rsa.h"
//#include "cryptopp/randpool.h"
//#include "cryptopp/hex.h"
//#include "cryptopp/base64.h"
//#include "cryptopp/osrng.h"
//#include "cryptopp/pem/pe
//using namespace CryptoPP;

#define ENCRYPT_SUCCESS 0
#define ENCRYPT_FAILED 1
#define ENCRYPT_WRONG_MSG "{\"code\":500, \"message\":\"encrypt error\"}"

CAIClient::CAIClient()
{
    QFile f(QCoreApplication::applicationDirPath() + "/config.json");
    if ( f.open(QFile::ReadOnly | QFile::Text) )
    {
        auto jdoc = QJsonDocument::fromJson(f.readAll());
        if ( jdoc.isObject() )
        {
            auto jobj = jdoc.object();
            m_url = jobj["url"].toString();
        }
        f.close();
    }
}

//void CAIClient::GenerateRSAKey(unsigned int keyLength, QString decFilename, QString encFilename, QString seed)
//{
//    RandomPool randPool;
//    randPool.IncorporateEntropy((byte *)seed.toStdString().c_str(), seed.length());

//    RSAES_OAEP_SHA_Decryptor decrypt(randPool, keyLength);
//    HexEncoder decFile(new Base64Encoder(new FileSink(decFilename.GetBuffer(decFilename.GetLength()))));

//    decrypt.(decFile);
//    decFile.MessageEnd();

//    RSAES_OAEP_SHA_Encryptor encrypt(decrypt);
//    HexEncoder encFile(new Base64Encoder(new FileSink(encFilename.GetBuffer(encFilename.GetLength()))));
//    encrypt.DEREncode(encFile);

//    encFile.MessageEnd();

//    return;
//}

int CAIClient::RSAEncryptString(QString smsg, QString &sencrypt)
{
    QString pem_path = QCoreApplication::applicationDirPath() + "/public.pem";
    qDebug()<<pem_path;
    auto f = fopen(pem_path.toStdString().c_str(), "rb");
    if ( !f )
    {
        return ENCRYPT_FAILED;
    }
    RSA *rsa = NULL;
    rsa = PEM_read_RSAPublicKey(f, &rsa, NULL, NULL);
    if ( !rsa )
        return ENCRYPT_FAILED;
    fclose(f);

    int rsa_len = RSA_size(rsa);

    unsigned char *sent = new unsigned char[rsa_len+1];
    memset(sent, 0, rsa_len+1);
    int encrypt_len = RSA_public_encrypt(smsg.length(), (unsigned char*)smsg.toStdString().c_str(), sent, rsa, RSA_PKCS1_PADDING);
    if ( encrypt_len < 0 )
    {
        delete []sent;
        return ENCRYPT_FAILED;
    }
    sencrypt = QByteArray(reinterpret_cast<char*>(sent),encrypt_len).toBase64();
    delete []sent;
    return ENCRYPT_SUCCESS;

//    char *cres = new char[255];
//    memset(cres, 0, 255);
//    base64_encode(sres.toStdString().c_str(), sres.length(), cres);
//    return cres;
//    QString skeyfile = "./public.pem";
//    QString key = "MIIBCgKCAQEAgBNzJ2FWbgqU/O4GgHEHeR2VkxK6ImNuFI7NwzgQVki4XWcFETux\nFBJWB+qDk+psM7Vz0zOqGrl3vCF9CkFOmZKZekNe0R5URfzute95VvzD0KSMYilC\nDeCLCTtqVIouVOT6IesYYp4sjH3gRTcUXrKA1BuFExVy4PpheGkvK9XE6bMFyQn/\ncJkghSC1h6vHbc5rWu6BWJYJ8PxiXALe1mrynzbhc6x/pEPEHNcQRpzI6wQIB0d7\nrA0HtEBDShAxGlJqdvBrZInD3obRYHdh001WijE6YXFmM1LStO5FQuFfS7iNS5Gj\nKJd8DdMxheUFmOkrl8FuP34Zi6+ROMck1QIDAQAB";
//            StringSource ss(key.toStdString().c_str(), true, new Base64Decoder);
//    RSA::PublicKey publicKey;
//    publicKey.Load(ss);
//            FileSource pubFile(skeyfile.toStdString().c_str(), true, new Base64Decoder);
//    RSAES_PKCS1v15_Encryptor pub(publicKey);
// PEM_
//        RandomPool randPool;
//        unsigned char seed[400] = "10";
//        randPool.IncorporateEntropy(seed, 2);

//        std::string result;
//        StringSource(smsg.toStdString(), true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
//        return result.c_str();
////    std::string encString;
////    CryptoPP::FileSource encFile(skeyfile.toStdString().c_str(), true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(encString)) );
//////    CryptoPP::HexDecoder decoder;
//////    decoder.Put( (unsigned char*)encString.c_str(), encString.size() );
////////    decoder.MessageEnd();

////    CryptoPP::RSAES_PKCS1v15_Encryptor enc(CryptoPP::StringSource(encString, true, new CryptoPP::Base64Decoder));
//////    enc.AccessKey().Load(decoder);

////    //unsigned char seed[400] = "10";
////    CryptoPP::AutoSeededRandomPool rnd;

////    std::string result;
////    CryptoPP::StringSource( smsg.toStdString(), true, new CryptoPP::PK_EncryptorFilter(rnd, enc, new CryptoPP::HexEncoder(new CryptoPP::StringSink(result))) );

////    return QString(result.c_str());

}

void CAIClient::setConfig(QString token)
{
    //m_url = url;
    m_token = token;
}

QString CAIClient::post_json(QString path, QByteArray &body) {
    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
    //设置url
    QString url = m_url + path;
    //设置头信息
    QNetworkRequest requestInfo;
    requestInfo.setUrl(QUrl(url));
    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));

    QString btoken("Bearer ");
    btoken += m_token;
    requestInfo.setRawHeader("Authorization", btoken.toUtf8());
    //  requestInfo.setRawHeader("Content-Type","application/json");//服务器要求的数据头部
    //  requestInfo.setRawHeader("Accept","text/json,*/*;q=0.5");//服务器要求的数据头部
//    QJsonObject jbody;
//    jbody["email"] = suser;
//    jbody["password"] = "EGqk1cEcb4q1qiFXz4rAs9CHuaeLNSBZPXm80lwi7kNccSonR+RumA5yB7LlwdOv1WkuYz7EL0bG\nYUOvOtijDdyngB5OiwqkqZyWSnc1UT9V53qBcVFKPNnaYxAgmY2KB1pJWSB0EQbwu//UcAN7XRPB\nDbLAO57Tstf85iYjdhr1Wzt3cG73JWb28L/OBDtpkal2wv36tzwia5VOftNYFUZZh8cgHiq+AtVT\nBJe90+fgQTgdgH2nypiozbSP+WcrdCX43aXXjftxzL4+r7QPv6+8UcjDSa0rXgxizuE6nFDN48/W\n2DBtnP30T5R8tswQNn8KrKgF0iE3A8C85FvFag==\n";
////    jbody["password"] = "MKmrvL0gnSzJvz+g+Cg97CLqjcRP9mfPvsqyI5UH0V8VJCYYJiUFhq2A1/qQNh3YPAbK+1DsIlhZ\nMXuDiy0HyccaGWObxuq3ifi3ylvo44ZVT3wLJBsuLKPY9b2tkxffUMdrO877ccRtUsBCs6by2fzT\nHC4R/0U9P5pmpXHrSr2sX/cR3EJ0prdgDEjFJfaN3HXIMmfqMWKCxPijrFVTbU67bhobhijts0xs\n2vA03yl6gBL2vpf//j98XPkNGXXr/ak9RWkkpBuSooAlZ05DhTdJLtfDe3bYHMvgorn5J4lePXXJ\nz2KZwUum1XxVnlw21/SdgjddGgWZtZO0b9YHmQ==\n";
//    QJsonDocument json_doc;
//    json_doc.setObject(jbody);
//    //发送数据
//    QByteArray qByteHttpData = json_doc.toJson();
    QNetworkReply *reply =  m_pHttpMgr->post(requestInfo, body);
    //添加事件循环机制，返回后再运行后面的
    QEventLoop eventLoop;
    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    eventLoop.exec();       //block until finish

    //错误处理
    if (reply->error() == QNetworkReply::NoError)
    {
        qDebug() << "request protobufHttp NoError";
    }
    else
    {
        qDebug()<<"request protobufHttp handle errors here";
        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
        qDebug(qPrintable(reply->errorString()));
    }

    //请求收到的结果
    QByteArray responseByte = reply->readAll();
    if ( reply )
        delete reply;
    if ( m_pHttpMgr )
        delete m_pHttpMgr;


    return QString(responseByte);
}

QString CAIClient::get_json(QString path, QByteArray &body) {
    QJsonDocument json_doc = QJsonDocument::fromJson(body);

    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
    //设置url
    QString url = m_url + path;
    //设置头信息
    QNetworkRequest requestInfo;
    QUrlQuery query;

    if ( json_doc.isObject() )
    {
        auto obj = json_doc.object();
        auto keys = obj.keys();
        for ( auto &key : keys ) {
            auto value = obj[key].toString();
            query.addQueryItem(key, value);
        }
    }

    QUrl qurl(url);
    qurl.setQuery(query);

    printf(qurl.url().toStdString().c_str());
    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));

    QString btoken("Bearer ");
    btoken += m_token;
    requestInfo.setRawHeader("Authorization", btoken.toUtf8());
    requestInfo.setUrl(qurl);
    //发送数据
    QByteArray qByteHttpData = "";
    QNetworkReply *reply =  m_pHttpMgr->get(requestInfo);
    //添加事件循环机制，返回后再运行后面的
    QEventLoop eventLoop;
    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    eventLoop.exec();       //block until finish

    //错误处理
    if (reply->error() == QNetworkReply::NoError)
    {
        qDebug() << "request protobufHttp NoError";
    }
    else
    {
        qDebug()<<"request protobufHttp handle errors here";
        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
        qDebug(qPrintable(reply->errorString()));
    }

    //请求收到的结果
    QByteArray responseByte = reply->readAll();
    if ( reply )
        delete reply;
    if ( m_pHttpMgr )
        delete m_pHttpMgr;


    return QString(responseByte);
}

QString CAIClient::post_multipart(QString path, QHttpMultiPart &body) {
    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
    //设置url
    QString url = m_url + path;
    //设置头信息
    QNetworkRequest requestInfo;
    requestInfo.setUrl(QUrl(url));
    //requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("multipart/form-data"));
    QString btoken("Bearer ");
    btoken += m_token;
    requestInfo.setRawHeader("Authorization", btoken.toUtf8());

    QNetworkReply *reply =  m_pHttpMgr->post(requestInfo, &body);
    //添加事件循环机制，返回后再运行后面的
    QEventLoop eventLoop;
    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    eventLoop.exec();       //block until finish

    //错误处理
    if (reply->error() == QNetworkReply::NoError)
    {
        qDebug() << "request protobufHttp NoError";
    }
    else
    {
        qDebug()<<"request protobufHttp handle errors here";
        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
        qDebug(qPrintable(reply->errorString()));
    }

    //请求收到的结果
    QByteArray responseByte = reply->readAll();
    if ( reply )
        delete reply;
    if ( m_pHttpMgr )
        delete m_pHttpMgr;


    return QString(responseByte);
}

QString CAIClient::get_computer_source() {
    QByteArray qByteHttpData = "";
    return this->get_json("/computersource", qByteHttpData);
}

QString CAIClient::login(QString suser, QString spassword) {
    QJsonObject jbody;
    jbody["email"] = suser;
    QString spassword_encrypt;
    auto res_encrypt = RSAEncryptString(spassword, spassword_encrypt);
    if ( ENCRYPT_SUCCESS != res_encrypt )
    {
        return ENCRYPT_WRONG_MSG;
    }
    jbody["password"] = spassword_encrypt;
    //jbody["password"] = "EGqk1cEcb4q1qiFXz4rAs9CHuaeLNSBZPXm80lwi7kNccSonR+RumA5yB7LlwdOv1WkuYz7EL0bG\nYUOvOtijDdyngB5OiwqkqZyWSnc1UT9V53qBcVFKPNnaYxAgmY2KB1pJWSB0EQbwu//UcAN7XRPB\nDbLAO57Tstf85iYjdhr1Wzt3cG73JWb28L/OBDtpkal2wv36tzwia5VOftNYFUZZh8cgHiq+AtVT\nBJe90+fgQTgdgH2nypiozbSP+WcrdCX43aXXjftxzL4+r7QPv6+8UcjDSa0rXgxizuE6nFDN48/W\n2DBtnP30T5R8tswQNn8KrKgF0iE3A8C85FvFag==\n";
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/user/login", qByteHttpData);

//    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
//    //设置url
//    QString url = m_url + "/user/login";
//    //设置头信息
//    QNetworkRequest requestInfo;
//    requestInfo.setUrl(QUrl(url));
//    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
//    //  requestInfo.setRawHeader("Content-Type","application/json");//服务器要求的数据头部
//    //  requestInfo.setRawHeader("Accept","text/json,*/*;q=0.5");//服务器要求的数据头部
//    QJsonObject jbody;
//    jbody["email"] = suser;
//    jbody["password"] = "EGqk1cEcb4q1qiFXz4rAs9CHuaeLNSBZPXm80lwi7kNccSonR+RumA5yB7LlwdOv1WkuYz7EL0bG\nYUOvOtijDdyngB5OiwqkqZyWSnc1UT9V53qBcVFKPNnaYxAgmY2KB1pJWSB0EQbwu//UcAN7XRPB\nDbLAO57Tstf85iYjdhr1Wzt3cG73JWb28L/OBDtpkal2wv36tzwia5VOftNYFUZZh8cgHiq+AtVT\nBJe90+fgQTgdgH2nypiozbSP+WcrdCX43aXXjftxzL4+r7QPv6+8UcjDSa0rXgxizuE6nFDN48/W\n2DBtnP30T5R8tswQNn8KrKgF0iE3A8C85FvFag==\n";
////    jbody["password"] = "MKmrvL0gnSzJvz+g+Cg97CLqjcRP9mfPvsqyI5UH0V8VJCYYJiUFhq2A1/qQNh3YPAbK+1DsIlhZ\nMXuDiy0HyccaGWObxuq3ifi3ylvo44ZVT3wLJBsuLKPY9b2tkxffUMdrO877ccRtUsBCs6by2fzT\nHC4R/0U9P5pmpXHrSr2sX/cR3EJ0prdgDEjFJfaN3HXIMmfqMWKCxPijrFVTbU67bhobhijts0xs\n2vA03yl6gBL2vpf//j98XPkNGXXr/ak9RWkkpBuSooAlZ05DhTdJLtfDe3bYHMvgorn5J4lePXXJ\nz2KZwUum1XxVnlw21/SdgjddGgWZtZO0b9YHmQ==\n";
//    QJsonDocument json_doc;
//    json_doc.setObject(jbody);
//    //发送数据
//    QByteArray qByteHttpData = json_doc.toJson();
//    QNetworkReply *reply =  m_pHttpMgr->post(requestInfo, qByteHttpData);
//    //添加事件循环机制，返回后再运行后面的
//    QEventLoop eventLoop;
//    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
//    eventLoop.exec();       //block until finish

//    //错误处理
//    if (reply->error() == QNetworkReply::NoError)
//    {
//        qDebug() << "request protobufHttp NoError";
//    }
//    else
//    {
//        qDebug()<<"request protobufHttp handle errors here";
//        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
//        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
//        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
//        qDebug(qPrintable(reply->errorString()));
//    }

//    //请求收到的结果
//    QByteArray responseByte = reply->readAll();
//    if ( reply )
//        delete reply;
//    if ( m_pHttpMgr )
//        delete m_pHttpMgr;


//    return QString(responseByte);
}

QString CAIClient::get_reset_validate_code(QString semail)
{
    QJsonObject jbody;
    jbody["email"] = semail;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/user/password/reset/email", qByteHttpData);
}

QString CAIClient::get_register_validate_code(QString semail)
{
    QJsonObject jbody;
    jbody["email"] = semail;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/user/register/validate", qByteHttpData);
}

QString CAIClient::reset_password(QString suser, QString svalidate_code, QString spassword)
{
    QJsonObject jbody;
    jbody["email"] = suser;
    jbody["validate_code"] = svalidate_code;
    QString spassword_encrypt;
    auto res_encrypt = RSAEncryptString(spassword, spassword_encrypt);
    if ( ENCRYPT_SUCCESS != res_encrypt )
    {
        return ENCRYPT_WRONG_MSG;
    }
    jbody["password"] = spassword_encrypt;
    //jbody["password"] = spassword;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/user/password/reset", qByteHttpData);
}

QString CAIClient::reset_password_by_auth(QString suser, QString spassword_old, QString spassword_new)
{
    QJsonObject jbody;
    jbody["email"] = suser;
    QString spassword_encrypt_old;
    auto res_encrypt = RSAEncryptString(spassword_old, spassword_encrypt_old);
    if ( ENCRYPT_SUCCESS != res_encrypt )
    {
        return ENCRYPT_WRONG_MSG;
    }
    jbody["password_old"] = spassword_encrypt_old;
//    jbody["password_old"] = spassword_old;
    QString spassword_encrypt_new;
    res_encrypt = RSAEncryptString(spassword_new, spassword_encrypt_new);
    if ( ENCRYPT_SUCCESS != res_encrypt )
    {
        return ENCRYPT_WRONG_MSG;
    }
    jbody["password_new"] = spassword_encrypt_new;
//    jbody["password_new"] = spassword_new;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/user/password/reset/auth", qByteHttpData);
}

QString CAIClient::register_user(QString suser, QString svalidate_code, QString spassword)
{
    QJsonObject jbody;
    jbody["email"] = suser;
    jbody["validate_code"] = svalidate_code;
    QString spassword_encrypt;
    auto res_encrypt = RSAEncryptString(spassword, spassword_encrypt);
    if ( ENCRYPT_SUCCESS != res_encrypt )
    {
        return ENCRYPT_WRONG_MSG;
    }
    jbody["password"] = spassword_encrypt;
    //jbody["password"] = spassword;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/user/register", qByteHttpData);
}

QString CAIClient::get_model(QString smodel_id)
{
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/model/get", qByteHttpData);
}

QString CAIClient::get_model_by_version(QString smodel_id, QString sversion)
{
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    jbody["commit_id"] = sversion;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/model/commit/get", qByteHttpData);
}

QString CAIClient::list_model() {
    QByteArray body;
    return get_json("/model/list", body);
//    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
//    //设置url
//    QString url = m_url + "/model/list";
//    //设置头信息
//    QNetworkRequest requestInfo;
//    requestInfo.setUrl(QUrl(url));
//    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));

//    QString btoken("Bearer ");
//    btoken += stoken;
//    requestInfo.setRawHeader("Authorization", btoken.toUtf8());

//    //发送数据
//    QByteArray qByteHttpData = "";
//    QNetworkReply *reply =  m_pHttpMgr->get(requestInfo);
//    //添加事件循环机制，返回后再运行后面的
//    QEventLoop eventLoop;
//    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
//    eventLoop.exec();       //block until finish

//    //错误处理
//    if (reply->error() == QNetworkReply::NoError)
//    {
//        qDebug() << "request protobufHttp NoError";
//    }
//    else
//    {
//        qDebug()<<"request protobufHttp handle errors here";
//        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
//        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
//        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
//        qDebug(qPrintable(reply->errorString()));
//    }

//    //请求收到的结果
//    QByteArray responseByte = reply->readAll();
//    if ( reply )
//        delete reply;
//    if ( m_pHttpMgr )
//        delete m_pHttpMgr;


//    return QString(responseByte);
}

QString CAIClient::list_dataset_public() {
    QByteArray body;
    return get_json("/dataset/public/list", body);
}


QString CAIClient::list_model_grant() {
    QByteArray body;
    return get_json("/model/list/grant", body);
}

QString CAIClient::list_model_user(QString smodel_id) {
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/model/grant/user/list", qByteHttpData);
}

QString CAIClient::list_model_public(){
    QByteArray body;
    return get_json("/model/public/list", body);
}

QString CAIClient::list_model_available() {
    QByteArray body;
    return get_json("/model/available/list", body);
}

QString CAIClient::create_model(QString smodel_name, QString smodel_class, QString sdependencies, QByteArray scontent, QString sdescription, QString stype, QString smodel_file_name, int ipublic, QString scommit)
{
    QHttpMultiPart multibody;
    multibody.setContentType(QHttpMultiPart::FormDataType);
//    multibody.setProperty("model_class", smodel_class);
//    multibody.setProperty("model_name", smodel_name);
//    multibody.set
    QHttpPart part_model_name;
    part_model_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_name\""));
    //part_model_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_model_name.setBody(smodel_name.toUtf8());
    multibody.append(part_model_name);

    QHttpPart part_model_class;
    part_model_class.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_class\""));
    //part_model_class.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_model_class.setBody(smodel_class.toUtf8());
    multibody.append(part_model_class);

    QHttpPart part_dependencies;
    part_dependencies.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"dependencies\""));
    //part_dependencies.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_dependencies.setBody(sdependencies.toUtf8());
    multibody.append(part_dependencies);

    QHttpPart part_description;
    part_description.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"description\""));
    part_description.setBody(sdescription.toUtf8());
    multibody.append(part_description);

    QHttpPart part_type;
    part_type.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_type\""));
    part_type.setBody(stype.toUtf8());
    multibody.append(part_type);

    QHttpPart part_file_name;
    part_file_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_file_name\""));
    part_file_name.setBody(smodel_file_name.toUtf8());
    multibody.append(part_file_name);

    QHttpPart part_commit;
    part_commit.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"commit_message\""));
    part_commit.setBody(scommit.toUtf8());
    multibody.append(part_commit);

    QHttpPart part_public;
    part_public.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"public\""));
    part_public.setBody(QString::number(ipublic).toUtf8());
    multibody.append(part_public);

    QHttpPart part_content;
    part_content.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"filebytes\"; filename=\"filebytes\""));
    part_content.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));

    part_content.setBody(scontent);
    multibody.append(part_content);

    return post_multipart("/model/create", multibody);
//    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
//    //设置url
//    QString url = m_url + "/model/create";
//    //设置头信息
//    QNetworkRequest requestInfo;
//    requestInfo.setUrl(QUrl(url));
//    //requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("multipart/form-data"));
//    QString btoken("Bearer ");
//    btoken += stoken;
//    requestInfo.setRawHeader("Authorization", btoken.toUtf8());
//    //  requestInfo.setRawHeader("Content-Type","application/json");//服务器要求的数据头部
//    //  requestInfo.setRawHeader("Accept","text/json,*/*;q=0.5");//服务器要求的数据头部
//    //QJsonObject jbody;
//    //jbody["email"] = suser;
//    //jbody["password"] = "MKmrvL0gnSzJvz+g+Cg97CLqjcRP9mfPvsqyI5UH0V8VJCYYJiUFhq2A1/qQNh3YPAbK+1DsIlhZ\nMXuDiy0HyccaGWObxuq3ifi3ylvo44ZVT3wLJBsuLKPY9b2tkxffUMdrO877ccRtUsBCs6by2fzT\nHC4R/0U9P5pmpXHrSr2sX/cR3EJ0prdgDEjFJfaN3HXIMmfqMWKCxPijrFVTbU67bhobhijts0xs\n2vA03yl6gBL2vpf//j98XPkNGXXr/ak9RWkkpBuSooAlZ05DhTdJLtfDe3bYHMvgorn5J4lePXXJ\nz2KZwUum1XxVnlw21/SdgjddGgWZtZO0b9YHmQ==\n";
//    //QJsonDocument json_doc;
//    //json_doc.setObject(jbody);


//    //发送数据
//    //QByteArray qByteHttpData = json_doc.toJson();
//    QNetworkReply *reply =  m_pHttpMgr->post(requestInfo, &multibody);
//    //添加事件循环机制，返回后再运行后面的
//    QEventLoop eventLoop;
//    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
//    eventLoop.exec();       //block until finish

//    //错误处理
//    if (reply->error() == QNetworkReply::NoError)
//    {
//        qDebug() << "request protobufHttp NoError";
//    }
//    else
//    {
//        qDebug()<<"request protobufHttp handle errors here";
//        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
//        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
//        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
//        qDebug(qPrintable(reply->errorString()));
//    }

//    //请求收到的结果
//    QByteArray responseByte = reply->readAll();
//    if ( reply )
//        delete reply;
//    if ( m_pHttpMgr )
//        delete m_pHttpMgr;


//    return QString(responseByte);
}

QString CAIClient::edit_model(QString smodel_id, QString smodel_name, QString smodel_class, QString sdependencies, QByteArray scontent, QString sdescription, QString stype, QString smodel_file_name, int ipublic, QString scommit)
{
    QHttpMultiPart multibody;
    multibody.setContentType(QHttpMultiPart::FormDataType);
//    multibody.setProperty("model_class", smodel_class);
//    multibody.setProperty("model_name", smodel_name);
//    multibody.set
    QHttpPart part_model_id;
    part_model_id.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_id\""));
    part_model_id.setBody(smodel_id.toUtf8());
    multibody.append(part_model_id);

    QHttpPart part_model_name;
    part_model_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_name\""));
    //part_model_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_model_name.setBody(smodel_name.toUtf8());
    multibody.append(part_model_name);

    QHttpPart part_model_class;
    part_model_class.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_class\""));
    //part_model_class.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_model_class.setBody(smodel_class.toUtf8());
    multibody.append(part_model_class);

    QHttpPart part_dependencies;
    part_dependencies.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"dependencies\""));
    //part_dependencies.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_dependencies.setBody(sdependencies.toUtf8());
    multibody.append(part_dependencies);

    QHttpPart part_description;
    part_description.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"description\""));
    part_description.setBody(sdescription.toUtf8());
    multibody.append(part_description);

    QHttpPart part_type;
    part_type.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_type\""));
    part_type.setBody(stype.toUtf8());
    multibody.append(part_type);

    QHttpPart part_file_name;
    part_file_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"model_file_name\""));
    part_file_name.setBody(smodel_file_name.toUtf8());
    multibody.append(part_file_name);

    QHttpPart part_commit;
    part_commit.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"commit_message\""));
    part_commit.setBody(scommit.toUtf8());
    multibody.append(part_commit);

    QHttpPart part_public;
    part_public.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"public\""));
    part_public.setBody(QString::number(ipublic).toUtf8());
    multibody.append(part_public);

    QHttpPart part_content;
    part_content.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"filebytes\"; filename=\"filebytes\""));
    part_content.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));

    part_content.setBody(scontent);
    multibody.append(part_content);

    return post_multipart("/model/edit", multibody);
}

QString CAIClient::delete_model(QString smodel_id)
{
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);

    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return post_json("/model/delete", qByteHttpData);

//    QNetworkAccessManager *m_pHttpMgr = new QNetworkAccessManager(this);
//    //设置url
//    QString url = m_url + "/model/delete";
//    //设置头信息
//    QNetworkRequest requestInfo;
//    requestInfo.setUrl(QUrl(url));
//    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
//    QString btoken("Bearer ");
//    btoken += stoken;
//    requestInfo.setRawHeader("Authorization", btoken.toUtf8());


//    QNetworkReply *reply =  m_pHttpMgr->post(requestInfo, qByteHttpData);
//    //添加事件循环机制，返回后再运行后面的
//    QEventLoop eventLoop;
//    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
//    eventLoop.exec();       //block until finish

//    //错误处理
//    if (reply->error() == QNetworkReply::NoError)
//    {
//        qDebug() << "request protobufHttp NoError";
//    }
//    else
//    {
//        qDebug()<<"request protobufHttp handle errors here";
//        QVariant statusCodeV = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
//        //statusCodeV是HTTP服务器的相应码，reply->error()是Qt定义的错误码，可以参考QT的文档
//        qDebug( "request protobufHttp found error ....code: %d %d\n", statusCodeV.toInt(), (int)reply->error());
//        qDebug(qPrintable(reply->errorString()));
//    }

//    //请求收到的结果
//    QByteArray responseByte = reply->readAll();
//    if ( reply )
//        delete reply;
//    if ( m_pHttpMgr )
//        delete m_pHttpMgr;


//    return QString(responseByte);
}

QString CAIClient::grant_model(QString smodel_id, QString semail, int role) {
    QJsonObject jbody;
    jbody["email"] = semail;
    jbody["model_id"] = smodel_id;
    jbody["role"] = role;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/model/grant", qByteHttpData);
}

QString CAIClient::delete_model_user(QString smodel_id, QString sgrant_id) {
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    jbody["grant_id"] = sgrant_id;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/model/grant/delete", qByteHttpData);
}

QString CAIClient::change_model_public(QString smodel_id, int ipublic) {
    QJsonObject jbody;
    jbody["model_id"] = smodel_id;
    jbody["public"] = ipublic;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/model/public/edit", qByteHttpData);
}

QString CAIClient::change_dataset_public(QString sdataset_id, int ipublic) {
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    jbody["public"] = ipublic;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/dataset/public/edit", qByteHttpData);
}


QString CAIClient::list_dataset() {
    QByteArray body;
    return get_json("/dataset/list", body);
}

QString CAIClient::list_dataset_grant() {
    QByteArray body;
    return get_json("/dataset/list/grant", body);
}

QString CAIClient::list_dataset_available() {
    QByteArray body;
    return get_json("/dataset/available/list", body);
}

QString CAIClient::list_dataset_user(QString sdataset_id) {
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/dataset/grant/user/list", qByteHttpData);
}

QString CAIClient::get_dataset(QString sdataset_id) {
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/dataset/get", qByteHttpData);
}

QString CAIClient::create_dataset(QString sdataset_name, QString sdataset_path, QString sdescription, int ipublic)
{
    QHttpMultiPart multibody;
    multibody.setContentType(QHttpMultiPart::FormDataType);
//    multibody.setProperty("model_class", smodel_class);
//    multibody.setProperty("model_name", smodel_name);
//    multibody.set
    QHttpPart part_dataset_name;
    part_dataset_name.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"dataset_name\""));
    //part_model_name.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
    part_dataset_name.setBody(sdataset_name.toUtf8());
    multibody.append(part_dataset_name);

    QHttpPart part_description;
    part_description.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"description\""));
    part_description.setBody(sdescription.toUtf8());
    multibody.append(part_description);

    QHttpPart part_public;
    part_public.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"public\""));
    part_public.setBody(QString::number(ipublic).toUtf8());
    multibody.append(part_public);

    QHttpPart part_content;
    part_content.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"filebytes\"; filename=\"filebytes\""));
    part_content.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
    QFile file(sdataset_path);
    if ( file.open(QFile::ReadOnly) )
    {
        part_content.setBody(file.readAll());
    }
    multibody.append(part_content);
    return post_multipart("/dataset/create", multibody);
}

QString CAIClient::edit_dataset(QString sdataset_id, QString sdataset_name, QString sdescription, int ipublic)
{
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    jbody["name"] = sdataset_name;
    jbody["description"] = sdescription;
    jbody["public"] = ipublic;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);

    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return post_json("/dataset/edit", qByteHttpData);
}

QString CAIClient::delete_dataset(QString sdataset_id)
{
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);

    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return post_json("/dataset/delete", qByteHttpData);
}

QString CAIClient::grant_dataset(QString sdataset_id, QString semail, int role) {
    QJsonObject jbody;
    jbody["email"] = semail;
    jbody["dataset_id"] = sdataset_id;
    jbody["role"] = role;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/dataset/grant", qByteHttpData);
}

QString CAIClient::delete_dataset_user(QString sdataset_id, QString sgrant_id) {
    QJsonObject jbody;
    jbody["dataset_id"] = sdataset_id;
    jbody["grant_id"] = sgrant_id;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/dataset/grant/delete", qByteHttpData);
}

QString CAIClient::list_trainjob()
{
    QByteArray body;
    return get_json("/trainjob/list", body);
}

QString CAIClient::get_trainjob(QString trainjob_id)
{
    QJsonObject jbody;
    jbody["trainjob_id"] = trainjob_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/trainjob/get", qByteHttpData);
}

QString CAIClient::create_trainjob(QString strain_dataset_id, QString sval_dataset_id, QString smodel_id, QString sname, QString sdescription, QString budget, QString train_args, int nversion)
{
    QJsonObject jbody;
    jbody["train_dataset_id"] = strain_dataset_id;
    jbody["val_dataset_id"] = sval_dataset_id;
    jbody["model_id"] = smodel_id;
    jbody["name"] = sname;
    jbody["description"] = sdescription;
    jbody["budget"] = budget;
    jbody["train_args"] = train_args;
    jbody["version"] = nversion;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/trainjob/create", qByteHttpData);
}

QString CAIClient::stop_trainjob(QString trainjob_id, QString status)
{
    QJsonObject jbody;
    jbody["trainjob_id"] = trainjob_id;
    jbody["status"] = status;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/trainjob/stop", qByteHttpData);
}

QString CAIClient::list_application()
{
    QByteArray body;
    return get_json("/application/list", body);
}

QString CAIClient::get_application(QString sapp_id)
{
    QJsonObject jbody;
    jbody["app_id"] = sapp_id;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/application/get", qByteHttpData);
}

QString CAIClient::create_application(QString sname, QString strainjob_id, QString sdescription)
{
    QJsonObject jbody;
    jbody["name"] = sname;
    jbody["trainjob_id"] = strainjob_id;
    jbody["description"] = sdescription;
    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/application/create", qByteHttpData);
}

QString CAIClient::stop_application(QString sapp_id, QString status)
{
    QJsonObject jbody;
    jbody["app_id"] = sapp_id;
    jbody["status"] = status;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/application/stop", qByteHttpData);
}

QString CAIClient::restart_application(QString sapp_id)
{
    QJsonObject jbody;
    jbody["app_id"] = sapp_id;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->post_json("/application/restart", qByteHttpData);
}

QString CAIClient::search_email(QString str)
{
    QJsonObject jbody;
    jbody["content"] = str;

    QJsonDocument json_doc;
    json_doc.setObject(jbody);
    //发送数据
    QByteArray qByteHttpData = json_doc.toJson();
    return this->get_json("/user/search", qByteHttpData);
}

